//
//  ProblemOffer12.swift
//  TestProject
//
//  Created by 武侠 on 2021/7/21.
//  Copyright © 2021 zhulong. All rights reserved.
//

import UIKit

/*
 剑指 Offer 12. 矩阵中的路径 ✅
 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中，返回 true ；否则，返回 false 。

 单词必须按照字母顺序，通过相邻的单元格内的字母构成，其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
 例如，在下面的 3×4 的矩阵中包含单词 "ABCCED"（单词中的字母已标出）。

 示例 1：
     输入：board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
     输出：true
 示例 2：
     输入：board = [["a","b"],["c","d"]], word = "abcd"
     输出：false
 提示：
     1 <= board.length <= 200
     1 <= board[i].length <= 200
     board 和 word 仅由大小写英文字母组成
 */
@objcMembers class ProblemOffer12: NSObject {
    func solution() {
        print(exist([["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], "ABCCED"))
        print(exist([["a","b"],["c","d"]], "abcd"))
        print(exist([["a"]], "a"))
        
        print(exist([["a","a"]], "aaa"))
    }
    
    /*
     1: 寻找单词的第一个字母在数组中的位置
     2: 判断当前位置是否满足需求
     */
    func exist(_ board: [[Character]], _ word: String) -> Bool {
        if word.count == 0 || word.count > board.count * board[0].count {
            return false
        }
        
        let sWord  = Array(word)
        var sBoard = board
        for (i, row) in board.enumerated() {
            for j in 0..<row.count {
                if sBoard[i][j] == sWord[0], isExistWord(&sBoard, i, j, 0, sWord) == true {
                    return true
                }
            }
        }
        
        return false
    }
    
    func isExistWord(_  board: inout [[Character]], _ i: Int, _ j: Int, _ k: Int, _ word: [Character]) -> Bool {
        if i < 0 || i >= board.count || j < 0 || j >= board[0].count || board[i][j] != word[k] {
            return false
        }
        if k == word.count - 1 {
            return true
        }
        board[i][j] = Character("\0")
        let isExist = isExistWord(&board, i, j+1, k+1, word) ||
                      isExistWord(&board, i, j-1, k+1, word) ||
                      isExistWord(&board, i+1, j, k+1, word) ||
                      isExistWord(&board, i-1, j, k+1, word)
        
        board[i][j] = word[k]
        return isExist
    }
    
}
